package hku.cs.lunuo.builders;

import hku.cs.lunuo.LunuoPlugin;
import hku.cs.lunuo.run.ThreadRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;

public class SootBuilder extends IncrementalProjectBuilder {

	public static final String BUILDER_ID = LunuoPlugin.PLUGIN_ID
			+ ".sootBuilder";
	
	private List<IJavaElement> shouldBuildClasses = new ArrayList<IJavaElement>();

	public SootBuilder() {
		// TODO Auto-generated constructor stub
	}

//	private class ThreadA extends Thread
//	{
//		List<IJavaElement> shouldBuildClasses;
//		IProgressMonitor monitor;
//		public ThreadA(List<IJavaElement> klasses, IProgressMonitor m){
//			shouldBuildClasses = klasses;
//			monitor = m;
//		}
//		
//		public void run(){
//			try {
//				Thread.sleep(100);
//			} catch (InterruptedException e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//			}
//			Runner runner = new Runner();
//			try {
//				runner.run(shouldBuildClasses, monitor);
//			} catch (CoreException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		}
//	}
	
	private void sootBuild(IProgressMonitor monitor){
		if(shouldBuildClasses.size() == 0)
			return;
		
//		new ThreadA(shouldBuildClasses, monitor).start();
//		Display d= Display.getCurrent();
		
		
//		Runner runner = new Runner();
//		try {
//			runner.run(shouldBuildClasses, monitor);
//		} catch (CoreException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		
		new ThreadRunner(JavaCore.create(getProject())).run(shouldBuildClasses);
		
		
		

//		new ThreadA(shouldBuildClasses).run();
		
		
		
//		try {
//			ModalContext.run(new IRunnableWithProgress() {
//				public void run(IProgressMonitor monitor)
//						throws InvocationTargetException, InterruptedException {
//					
//					Runner runner = new Runner();
//    				try {
//    					runner.run(shouldBuildClasses, monitor);
//    				} catch (CoreException e) {
//    					// TODO Auto-generated catch block
//    					e.printStackTrace();
//    				}
//					ModalContext.checkCanceled(monitor);
//				}
//			}, true, new NullProgressMonitor(), Display.getDefault());
//		} catch (InvocationTargetException e) {
//
//		} catch (InterruptedException e) {
//		} 
		
//		Job job = new Job("heloo"){
//			protected IStatus run(IProgressMonitor monitor){
//			    Display.getDefault().asyncExec(
//			    		new Runnable(){
//			    			public void run(){
//			    				Runner runner = new Runner();
//			    				try {
//			    					runner.run(shouldBuildClasses);
//			    				} catch (CoreException e) {
//			    					// TODO Auto-generated catch block
//			    					e.printStackTrace();
//			    				}
//			    			}
//			    		}
//			    );
//			    return Status.OK_STATUS; 
//			}
//		};
//		job.schedule();
		
			
//			IJavaProject ijp = JavaCore.create(file.getProject());
//			try {
//				if(ijp.getOutputLocation().isPrefixOf(JavaCore.create(file).getPath())){
//					Runner runner = new Runner();
//					try {
//						runner.run(JavaCore.create(file));
//					} catch (CoreException e) {
//						// TODO Auto-generated catch block
//						e.printStackTrace();
//					}
//				}
//			} catch (JavaModelException e1) {
//				// TODO Auto-generated catch block
//				e1.printStackTrace();
//			}
//		
//			List<IJavaElement> changedRes = new ArrayList<IJavaElement>();
//			changedRes.add(JavaCore.create(file));
//			
//			LunuoLaunchManager llm = new LunuoLaunchManager(LunuoLaunchManager.INCBUILD, changedRes);
//			llm.run();
			
	}
	
	
	
	class SampleDeltaVisitor implements IResourceDeltaVisitor {
		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
		 */
		public boolean visit(IResourceDelta delta) throws CoreException {
			IResource resource = delta.getResource();
			switch (delta.getKind()) {
			case IResourceDelta.ADDED:
				// handle added resource
				shouleBuildAndAdd(resource);
				break;
			case IResourceDelta.REMOVED:
				// handle removed resource
				break;
			case IResourceDelta.CHANGED:
				// handle changed resource
				shouleBuildAndAdd(resource);
				break;
			}
			//return true to continue visiting children.
			return true;
		}

		
	}
	

	class SampleResourceVisitor implements IResourceVisitor {
		public boolean visit(IResource resource) {
			shouleBuildAndAdd(resource);
			//return true to continue visiting children.
			return true;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.internal.events.InternalBuilder#build(int,
	 *      java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
			throws CoreException {
		shouldBuildClasses.clear();
				
		
		if (kind == FULL_BUILD) {
			fullBuild(monitor);
		} else {
			IResourceDelta delta = getDelta(getProject());
			if (delta == null) {
				fullBuild(monitor);
			} else {
				incrementalBuild(delta, monitor);
			}
		}
		sootBuild(monitor);
		return null;
	}

	

	protected void fullBuild(final IProgressMonitor monitor)
			throws CoreException {
		try {
			getProject().accept(new SampleResourceVisitor());
		} catch (CoreException e) {
		}
	}



	protected void incrementalBuild(IResourceDelta delta,
			IProgressMonitor monitor) throws CoreException {
		// the visitor does the work.
		delta.accept(new SampleDeltaVisitor());
	}
	
	private boolean shouleBuildAndAdd(IResource resource) {
		if (resource instanceof IFile && resource.getName().endsWith(".java")) {
			IFile file = (IFile) resource;
			shouldBuildClasses.add(JavaCore.create(file));
			return true;
		}
		return false;
	}
	
	
	
}
